use std::{
    fs,
    path::{Path, PathBuf},
    process::Command,
};

use crate::video_cap::find_img_pos_ms;

pub mod img;
pub mod video_cap;

/**
 * 剪切
 * video_path_str:
 * target_img_str:
 * skip_time:
 * ad_time:
 *
 */
pub async fn video_cut(video_path_str: &str, target_img_str: &str, skip_time: f64, ad_time: f64) {
    let video_path = Path::new(video_path_str);

    if !video_path.exists() {
        eprintln!("视频文件不存在!");
        return;
    }

    let target_img_path = Path::new(target_img_str);
    if !target_img_path.exists() {
        eprintln!("需要查询的图片不存在!");
        return;
    }

    let video_path = video_path.canonicalize().unwrap_or_default();
    let target_img_path = target_img_path.canonicalize().unwrap_or_default();

    let dir = video_path.parent().unwrap();

    let file_name = video_path
        .file_name()
        .unwrap()
        .to_string_lossy()
        .to_string();

    let video_path_str = video_path.to_string_lossy().to_string();
    let target_img_str = target_img_path.to_string_lossy().to_string();
    println!("[video_path]: {}", video_path_str);
    println!("[dir]: {}", dir.to_string_lossy().to_string());
    println!("[file_name]: {}", file_name);

    let pos_ms = find_img_pos_ms(&video_path_str, &target_img_str, skip_time, None).unwrap();

    if pos_ms.is_none() {
        ()
    }

    let out_dir = dir.join("output");
    if !&out_dir.exists() {
        fs::create_dir(&out_dir).unwrap();
    }

    // 生成视频输入文件
    let (list_file, part0, part1) = generate_list_file(&out_dir, &file_name);
    println!("[list_file]: {:?}", &list_file.to_string_lossy());

    let cmd = format!(
        "ffmpeg -ss 0.0 -to '{}ms' -i '{}' -y -f mp4 -vcodec copy -acodec copy -q:v 1 '{}'",
        pos_ms.unwrap(),
        video_path.to_string_lossy(),
        part0.to_string_lossy(),
    );

    println!("{cmd}");
    exec_command(&cmd);

    let pos_ms = pos_ms.unwrap() + ad_time;
    let cmd = format!(
        "ffmpeg -ss '{}ms' -i '{}' -y -f mp4 -vcodec copy -acodec copy -q:v 1 '{}'",
        pos_ms,
        video_path.to_string_lossy(),
        part1.to_string_lossy(),
    );
    println!("{cmd}");
    exec_command(&cmd);

    // 输出视频文件
    let output_vide_file = out_dir.join(file_name.as_str());
    let cmd = format!(
        "ffmpeg -f concat -safe 0 -i '{}' -acodec copy -vcodec copy '{}'",
        &list_file.to_string_lossy(),
        output_vide_file.to_string_lossy(),
    );
    println!("{cmd}");
    exec_command(&cmd);

    fs::remove_file(part0).unwrap();
    fs::remove_file(part1).unwrap();
    fs::remove_file(list_file).unwrap();
}

/**
 * 生成两片视频的list文件
 */
fn generate_list_file(output_dir: &PathBuf, file_name: &str) -> (PathBuf, PathBuf, PathBuf) {
    let src_file_name = format!("{}.txt", file_name);
    let video_src_file = &output_dir.join(src_file_name.as_str());

    let part_file_0 = &output_dir.join(format!("{}_part_0.mp4", file_name));
    let part_file_1 = &output_dir.join(format!("{}_part_1.mp4", file_name));

    exec_command(
        format!(
            "echo 'file {}' > {}",
            part_file_0.to_string_lossy(),
            video_src_file.to_string_lossy()
        )
        .as_str(),
    );
    exec_command(
        format!(
            "echo 'file {}' >> {}",
            part_file_1.to_string_lossy(),
            video_src_file.to_string_lossy()
        )
        .as_str(),
    );

    (
        video_src_file.clone(),
        part_file_0.clone(),
        part_file_1.clone(),
    )
}

/**
 * command 执行命令
 */
fn exec_command(cmd: &str) {
    let _ = Command::new("bash")
        .arg("-c")
        .arg(cmd)
        .output()
        .expect("Failed to execute command");
}
